(define (not x)            (if x #f #t))
(define (null? obj)        (if (eqv? obj '()) #t #f))

(define (id obj)           obj)

(define (flip func)        (lambda (arg1 arg2) (func arg2 arg1)))

(define (odd? num)         (= (mod num 2) 1))
(define (even? num)        (= (mod num 2) 0))

(define snoc               (flip cons))

(define (foldr func end lst)
    (if (null? lst)
        end
        (func (car lst) (foldr func end (cdr lst)))))

(define (foldl func acc lst)
    (if (null? lst)
        acc
        (foldl func (func acc (car lst)) (cdr lst))))

(define (map func lst) 
    (if (null? lst)
        '()
        (cons (func (car lst)) (map func (cdr lst)))))

(define (filter pred lst)
    (if (null? lst)
        '()
        (if (pred (car lst))
            (cons (car lst) (filter pred (cdr lst)))
            (filter pred (cdr lst)))))

(define (sum lst)         (foldl + 0 lst))
(define (product lst)     (foldl * 1 lst))
(define (length lst)      (foldl (lambda (x y) (+ x 1)) 0 lst))
(define (reverse lst)     (foldl snoc '() lst))